package cn.xiangxiang.service.impl;

import cn.xiangxiang.CacheKey;
import cn.xiangxiang.mapper.goods.BrandMapper;
import cn.xiangxiang.mapper.goods.SkuMapper;
import cn.xiangxiang.mapper.goods.SpecMapper;
import cn.xiangxiang.pojo.goods.Sku;
import cn.xiangxiang.service.goods.SkuService;
import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service(interfaceClass = SkuService.class)
public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements SkuService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private BrandMapper brandMapper;

    @Autowired
    private SpecMapper specMapper;

    /**
     * 根据spuid查询对应sku列表
     * @param spuId
     * @return
     */
    public List<Sku> findBySpuId(String spuId) {

        HashMap<String, Object> map = new HashMap<>();
        map.put("spu_id",spuId);
        List<Sku> skuList = listByMap(map);

        return skuList;
    }

    /**
     * 根据id去缓存中查询价格
     * @param skuId
     * @return
     */
    public Integer getPrice(String skuId) {
        return (Integer) redisTemplate.boundHashOps(CacheKey.SKU_PRICE).get(skuId);
    }

    /**
     * 缓存价格到redis
     */
    public void saveToRedis() {
        List<Sku> skuList = list();
        for (Sku sku : skuList) {
            if("1".equals(sku.getStatus())){
                redisTemplate.boundHashOps(CacheKey.SKU_PRICE).put(sku.getId(),sku.getPrice());
            }
        }
    }

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    //查询方法
    public Map<String, Object> search(Map searchMap) {
        HashMap<String, Object> dataMap = new HashMap<>();

        SearchRequest searchRequest = new SearchRequest("skuu");
        searchRequest.types("doc");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


        if(!"".equals(searchMap.get("orderName"))){
            sourceBuilder.sort((String) searchMap.get("orderName"), SortOrder.valueOf("DESC"));

        }

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name").preTags("<font style=color:red><b>").postTags("</b></font>");

        sourceBuilder.highlighter(highlightBuilder);


        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        TermQueryBuilder termQuery = QueryBuilders.termQuery("name", searchMap.get("keyword"));
        boolQuery.must(termQuery);


        Integer pageNo = Integer.valueOf((String) searchMap.get("pageNo"));
        if(pageNo<=0){
            pageNo=1;
        }
        Integer pageSize = 30;
        pageNo = (pageNo-1)*pageSize;
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);


//        分类
        String categoryName = (String) searchMap.get("categoryName");
        if(categoryName!=null){
            TermQueryBuilder termQuery2 = QueryBuilders.termQuery("categoryName",categoryName );
            boolQuery.must(termQuery2);
        }

//        品牌
        String brandName = (String) searchMap.get("brandName");
        if(brandName!=null){
            TermQueryBuilder queryBuilder = QueryBuilders.termQuery("brandName", brandName);
            boolQuery.filter(queryBuilder);
        }

//        规格组建
        for (Object key : searchMap.keySet()) {
             String k = (String) key;
            if(k.startsWith("spec.")){
                TermQueryBuilder queryBuilder = QueryBuilders.termQuery(k + ".keyword", searchMap.get(k));
                boolQuery.filter(queryBuilder);
            }
        }

//        价格
        String price = (String) searchMap.get("price");
        if(price!=null) {
            String[] prices = price.split("-");
            if (!"0".equals(prices[0])) {
                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price").gte(prices[0] + "00");
                boolQuery.filter(rangeQueryBuilder);
            }
            if (!"*".equals(prices[1])) {
                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price").lte(prices[1] + "00");
                boolQuery.filter(rangeQueryBuilder);
            }
        }

        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("cku_category").field("categoryName");

        sourceBuilder.aggregation(aggregationBuilder);

        sourceBuilder.query(boolQuery);

        searchRequest.source(sourceBuilder);




        try {
            // 1 数据
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] hits = response.getHits().getHits();
            ArrayList<Map> rows = new ArrayList<>();
            for (SearchHit hit : hits) {
                Text name = hit.getHighlightFields().get("name").getFragments()[0];
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                sourceAsMap.put("name",name.toString());
                rows.add(sourceAsMap);
            }
            dataMap.put("rows",rows);

            // 构建总页数
            long total = response.getHits().getTotalHits();
            Long pageTotal = total%pageSize==0?total/pageSize:total/pageSize+1;

            dataMap.put("pageTatol",pageTotal.intValue());


//            2 分类数据
            Aggregations aggregations = response.getAggregations();
            Map<String, Aggregation> categoryMap = aggregations.getAsMap();
            Terms terms = (Terms) categoryMap.get("cku_category");
            ArrayList<String> categoryList = new ArrayList<>();
            for (Terms.Bucket bucket : terms.getBuckets()) {
                categoryList.add(bucket.getKeyAsString());
            }

            dataMap.put("categoryList",categoryList);


            // 品牌列表
            ArrayList<Map> brandList = new ArrayList<>();
            if(categoryList.size()>0) {
                if (categoryName == null) {
                    brandList = (ArrayList<Map>) brandMapper.findBrandByCategoryName(categoryList.get(0));
                } else {
                    brandList = (ArrayList<Map>) brandMapper.findBrandByCategoryName(categoryName);
                }
            }

            dataMap.put("brandList",brandList);


            // 规格列表
            ArrayList<Map> specList = new ArrayList<>();
            if(categoryList.size()>0){
                if(categoryName!=null){
                    specList = (ArrayList<Map>) specMapper.findListByCategoryName(categoryName);
                }else{
                    specList = (ArrayList<Map>) specMapper.findListByCategoryName(categoryList.get(0));
                }
            }

            specList.forEach((specMap)->{
                 String options = (String) specMap.get("options");
                 specMap.put("options",options.split(","));
            });
            dataMap.put("specList",specList);

        } catch (IOException e) {
            e.printStackTrace();
        }


        return dataMap;
    }

}
